package yx.action;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.springframework.beans.factory.annotation.Autowired;

import yx.model.BsGrade;
import yx.service.CourseServiceInt;
import yx.service.GradeServiceInt;
import yx.service.StudentServiceInt;
import yx.utils.ExcelUtils;
import yx.vo.CourseVO;
import yx.vo.DatagridVO;
import yx.vo.GradeVO;
import yx.vo.JsonVO;
import yx.vo.StudentVO;

import com.opensymphony.xwork2.ModelDriven;

@ParentPackage("basePackage")
@Namespace("/")
@Action(value = "gradeAction")
public class GradeAction extends BaseAction implements ModelDriven<GradeVO> {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(GradeAction.class);

	private GradeVO grade = new GradeVO();

	@Override
	public GradeVO getModel() {
		return grade;
	}

	private GradeServiceInt gradeService;
	private StudentServiceInt studentService;
	private CourseServiceInt courseService;

	public GradeServiceInt getGradeService() {
		return gradeService;
	}

	@Autowired
	public void setGradeService(GradeServiceInt gradeService) {
		this.gradeService = gradeService;
	}

	public StudentServiceInt getStudentService() {
		return studentService;
	}

	@Autowired
	public void setStudentService(StudentServiceInt studentService) {
		this.studentService = studentService;
	}

	public CourseServiceInt getCourseService() {
		return courseService;
	}

	@Autowired
	public void setCourseService(CourseServiceInt courseService) {
		this.courseService = courseService;
	}

	public void queryGrade() {
		super.writeJson(gradeService.datagrid(grade));
	}

	public void addGrade() {
		JsonVO j = new JsonVO();
		try {
			GradeVO u = gradeService.save(grade);
			j.setSuccess(true);
			j.setMsg("增加成功！");
			j.setObj(u);
		} catch (Exception e) {
			j.setMsg(e.getMessage());
		}
		super.writeJson(j);
	}

	public void removeGrade() {
		gradeService.remove(grade.getIds());
		JsonVO j = new JsonVO();
		j.setSuccess(true);
		j.setMsg("删除成功！");
		super.writeJson(j);
	}

	public void editGrade() {
		GradeVO u = gradeService.edit(grade);
		JsonVO j = new JsonVO();
		j.setSuccess(true);
		j.setMsg("编辑成功！");
		j.setObj(u);
		super.writeJson(j);
	}

	public void importGrade() {
		JsonVO j = new JsonVO();
		try {
			// 第一步：读取预置的模板
			String templatePath = ServletActionContext.getServletContext().getRealPath("/") + "template\\GradeImport.xlsx";
			Map<Integer, Boolean> mapCell = ExcelUtils.resolveExcelTemplate(templatePath);
			InputStream inp = new FileInputStream(grade.getImportGrade());
			XSSFWorkbook wb = new XSSFWorkbook(inp);
			int countCell = mapCell.size(); // 模板 列数
			List<BsGrade> importGradeList = new ArrayList<BsGrade>();
			// 导入列里 已经存在的 用户编码 集合 K用户编码 V所在Excel中第几行
			Map<String, Integer> importGradeMap = new HashMap<String, Integer>();
			XSSFSheet sheet = wb.getSheetAt(0); // 只 读取 第一个 sheet
			if (sheet.getLastRowNum() == 0) {
				throw new Exception("导入文件中数据不存在！");
			}
			int rownum = sheet.getLastRowNum() + 1;
			XSSFRow row = sheet.getRow(0);
			int cellnum = row.getLastCellNum();
			if (cellnum != countCell) {
				throw new Exception("数据格式和模板不一致！");
			}
			// Key：行号 Value：行的错误ArrayList
			Map<String, List<String>> errorMap = new HashMap<String, List<String>>();

			// 遍历数据行 从 索引为1开始 因为第一行是标题
			for (int index = 1; index < rownum; index++) {
				row = sheet.getRow(index);
				if (row == null || row.getLastCellNum() == 0)
					continue;
				List<String> dataList = new ArrayList<String>();
				List<String> errorList = new ArrayList<String>();
				String r1c1Cell = null;
				for (int cellindex = 0; cellindex < cellnum; cellindex++) {
					XSSFCell cell = row.getCell(cellindex);
					String cellStr = ExcelUtils.getExcelCellValue(cell);
					if (cellindex == 0) {
						r1c1Cell = cellStr;
					}
					if (mapCell.get(cellindex) && cell == null) {
						errorList.add("第" + (cellindex + 1) + "列不能为空！");
					} else {
						if (cellindex == 1 && cell != null) { // 第二列为学号且姓名+学号不能重复
							if (!importGradeMap.containsKey(cellStr)) {
								StudentVO stuVO = new StudentVO();
								stuVO.setStudentName(r1c1Cell);
								stuVO.setStudentNo(cellStr);
								StudentVO stu = hasStudent(stuVO.getStudentName(), stuVO.getStudentNo());
								if (stu == null) {
									errorList.add("第" + (cellindex + 1) + "列[姓名+学号]不存在！");
								} else {
									cellStr = stu.getId().toString();
									importGradeMap.put(cellStr, cellindex + 1);
								}
							} else {
								errorList.add("第" + (cellindex + 1) + "列[学号]与Excel第" + importGradeMap.get(cellStr) + "行学号相同！");
							}
						}
						if (cellindex == 2 && cell != null) { // 第三列为课程名称
							CourseVO courseVO = new CourseVO();
							courseVO.setCourseName(cellStr);
							CourseVO c = hasCourse(courseVO);
							if (c == null) {
								errorList.add("第" + (cellindex + 1) + "列[课程名称]不存在！");
								cellStr = null;
							} else {
								cellStr = c.getId().toString();
							}
						}
					}
					dataList.add(cellStr);
					errorMap.put((index + 1) + "", errorList);
				}
				Integer studentId = Integer.valueOf(dataList.get(1));
				Integer courseId = Integer.valueOf(dataList.get(2));
				boolean ret = hasGrade(studentId, courseId);
				if (ret) {
					errorList.add("导入数据已经存在！");
				}
				StringBuffer rowErrMsgSb = new StringBuffer("");
				List<String> tempList = errorMap.get((index + 1) + "");
				if (tempList != null) {
					for (int n = 0; n < tempList.size(); n++) {
						String str = (String) tempList.get(n);
						rowErrMsgSb.append(str);
					}
				}

				// 判断当前行是否有错
				if ("".equals(rowErrMsgSb.toString())) {
					BsGrade importGrade = new BsGrade();
					importGrade.setStudentId(Integer.valueOf(dataList.get(1)));
					importGrade.setCourseId(Integer.valueOf(dataList.get(2)));
					Float examScore = dataList.get(3) == null ? null : Float.valueOf(dataList.get(3));
					importGrade.setExamScore(examScore);
					Float homeworkScore = dataList.get(4) == null ? null : Float.valueOf(dataList.get(4));
					importGrade.setHomeworkScore(homeworkScore);
					Float attendanceScore = dataList.get(5) == null ? null : Float.valueOf(dataList.get(5));
					importGrade.setAttendanceScore(attendanceScore);
					importGrade.setOverallScore(dataList.get(6));
					importGrade.setMemo(dataList.get(7));
					importGradeList.add(importGrade);
				}
			}

			// 判断是否有错
			StringBuffer tempErrMsg = new StringBuffer("");
			for (int ind = 1; ind <= rownum; ind++) {
				List<String> tempList = errorMap.get(ind + "");
				if (tempList != null) {
					for (int t = 0; t < tempList.size(); t++) {
						String str = (String) tempList.get(t);
						tempErrMsg.append(str);
					}
				}
			}

			// 出错处理
			StringBuffer allErrMsg = new StringBuffer("");
			if (!"".equals(tempErrMsg.toString())) {
				for (int ind = 1; ind <= rownum; ind++) {
					List<String> errList = errorMap.get(ind + "");
					String tempErr = "";
					if (errList == null || errList.size() == 0) {
						// 无错
						continue;
					} else {
						StringBuffer sb = new StringBuffer();
						sb.append("第" + ind + "行：");
						java.util.Iterator it = (java.util.Iterator) errList.iterator();
						while (it.hasNext()) {
							String item = (String) it.next();
							sb.append(item + ",");
						}
						tempErr = sb.toString().substring(0, sb.toString().length() - 1) + "\\n";
					}
					allErrMsg.append(tempErr);
				}
				throw new Exception(allErrMsg.toString());
			} else {
				gradeService.saveAll(importGradeList);
				j.setSuccess(true);
				j.setMsg("导入成功！");
				super.writeJson(j);
			}
		} catch (Exception e) {
			j.setMsg(e.getMessage());
			super.writeJson(j);
		}
	}

	public void downloadTemplate() {
		OutputStream os = null;
		byte[] bytes = null;
		try {
			String downloadPath = ServletActionContext.getServletContext().getRealPath("/") + "template\\GradeImport.xlsx";
			bytes = gradeService.getFileBytes(downloadPath);
			ServletActionContext.getResponse().reset();
			ServletActionContext.getResponse().setCharacterEncoding("utf-8");
			ServletActionContext.getResponse().setHeader("Content-Type", "application/octet-stream");
			ServletActionContext.getResponse().setHeader("Content-Disposition", "attachment; filename=GradeImport.xlsx");
			os = ServletActionContext.getResponse().getOutputStream();
			if (bytes != null) {
				os.write(bytes);
				os.flush();
				os.close();
			}
			logger.info("文档下载成功！");
		} catch (Exception e) {
			logger.error("文档下载失败！");
		} finally {
			try {
				if (bytes != null) {
					os.write(bytes);
					os.flush();
				}
				os.close();
			} catch (IOException e) {
				logger.error("流文件关闭异常！");
			}
		}
	}

	private StudentVO hasStudent(String studentName, String studentNo) {
		StudentVO vo = null;
		List<StudentVO> list = studentService.queryStudentByNameAndNo(studentName, studentNo);
		if (list.size() > 0) {
			vo = list.get(0);
			return vo;
		}
		return vo;
	}

	private CourseVO hasCourse(CourseVO course) {
		DatagridVO vo = courseService.datagrid(course);
		if (vo.getTotal() > 0) {
			CourseVO courseVO = (CourseVO) vo.getRows().get(0);
			return courseVO;
		}
		return null;
	}

	private boolean hasGrade(Integer studentId, Integer courseId) {
		List<GradeVO> retlist = gradeService.queryGradeByStudentIdAndCourseId(studentId, courseId);
		if (retlist.size() > 0) {
			return true;
		}
		return false;
	}

}
